
package com.newx.test.open.tcp4;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Classname MCUServer1
 * @Description 单片机通信服务端
 * @Date 2025/1/7 16:24
 * @Created by yxl
 */
public class MCUServer1 {

    public static final int BUFFER_SIZE = 1; // 每个数据包的最大大小
    public static final int TIMEOUT_MS = 5000;  // 确认超时时间（毫秒）

    private static final ExecutorService threadPool = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        String host = "127.0.0.1"; // 本地回环地址
        int port = 5000; // 监听端口

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Java服务端正在监听 " + host + ":" + port + "...");

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("收到客户端连接请求");

                // 使用线程池处理每个客户端连接
                threadPool.submit(() -> handleClient(clientSocket));
            }
        } catch (IOException e) {
            System.err.println("无法绑定到端口: " + e.getMessage());
        } finally {
            threadPool.shutdown();
        }
    }

    private static void handleClient(Socket clientSocket) {
        try (
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                DataOutputStream outStream = new DataOutputStream(clientSocket.getOutputStream())
        ) {
            System.out.println("处理来自 " + clientSocket.getInetAddress() + " 的连接");

            // 等待客户端发送消息
            String message;
            while ((message = in.readLine()) != null) {
                System.out.println("收到客户端消息: " + message);

                // 根据接收到的消息准备发送文件
                if ("Request file".equalsIgnoreCase(message)) {
                    System.out.println("等待用户确认发送文件...");

                    // 等待用户输入命令
                    BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
//                    System.out.print("请输入 'send' 来发送文件: ");

//                    String userCommand = userInput.readLine();
//
//                    if ("send".equalsIgnoreCase(userCommand)) {
//                        sendFile(outStream, in, "F:\\Desktop\\111.txt");
//                    } else {
//                        System.out.println("未发送文件，继续等待...");
//                    }
                    // 此处执行业务操作
                    // 1、发送文件
                    sendFile(outStream, in, "F:\\Desktop\\111.txt");
                    // 2、业务操作
                    // 3、添加日志
                    break;
                } else {
                    outStream.writeUTF("Unknown command");
                    outStream.flush();
                }
            }
        } catch (IOException e) {
            System.err.println("处理客户端时发生IO异常: " + e.getMessage());
        }
    }

    private static void sendFile(DataOutputStream outStream, BufferedReader in, String filePath) throws IOException {
        Path path = Paths.get(filePath);
        if (!Files.exists(path)) {
            outStream.writeUTF("File not found: " + filePath);
            outStream.flush();
            return;
        }

        File file = path.toFile();
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead;

        // 发送文件名和文件大小
        outStream.writeUTF(file.getName());
        outStream.writeLong(file.length());
        outStream.flush();

        // 发送文件内容，分包处理
        int packetNumber = 0;
        while ((bytesRead = fis.read(buffer)) != -1) {
            // 发送数据包
            outStream.writeInt(packetNumber); // 数据包序号
            outStream.writeInt(bytesRead);    // 数据长度
            outStream.write(buffer, 0, bytesRead);
            outStream.flush();

            // 等待确认
            String ack = in.readLine();
            if (ack == null || !ack.equals("ACK " + packetNumber)) {
                System.out.println("未收到确认，重传数据包 " + packetNumber);
                fis.getChannel().position(fis.getChannel().position() - bytesRead);
                continue;
            }
            System.out.println("收到确认，继续发送下一个数据包 " + packetNumber);
            packetNumber++;
        }

        fis.close();
        System.out.println("文件发送完成: " + filePath);
    }
}